package com.hisee.util;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.joda.time.DateTime;

import com.hisee.bean.BSImgBean;
import com.hisee.bean.PhotoBean;
import com.hisee.writedb.WriteMysql;
import com.ibm.mq.MQException;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQPutMessageOptions;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.constants.CMQC;
import com.ibm.mq.constants.MQConstants;

/**
 * 业务类 zh new
 * 
 */
public class BsUtil2 {

	@SuppressWarnings("rawtypes")
	private static Hashtable<String, Comparable> env = new Hashtable<String, Comparable>();

	// 队列管理器名
	private static String queueManagerName;
	// 队列管理器引用
	private static MQQueueManager queueManager;
	// 队列名
	private static String queueName;
	// 队列引用
	private static MQQueue queue;

	/**
	 * <b>应用启动时初始化队列管理器连�?/b> <br>
	 * 由于连接队列管理器如同连接数据一样，建立时需要资源较多， 连接时间较长�?因此不要每次创建关闭�?建议应用程序保持�?�� 或多个队列管理器连接�?
	 * 但应用关闭时注意关闭连接，释放资源！
	 * 
	 * @throws Exception
	 */
	public static void initEnvironment() throws Exception {
		// 服务器地id、名称 正式环境地址：194.1.14.204
		env.put(CMQC.HOST_NAME_PROPERTY, "194.1.14.132");
		// 连接通道
		env.put(CMQC.CHANNEL_PROPERTY, "IE.SVRCONN");
		// 服务器MQ服务使用的编1381代表GBK,1208代表UTF(Coded Character Set Identifier:CCSID)
		env.put(CMQC.CCSID_PROPERTY, 1208);
		// 端口号
		env.put(CMQC.PORT_PROPERTY, 5000);
		// 传输类型
		env.put(CMQC.TRANSPORT_PROPERTY, CMQC.TRANSPORT_MQSERIES);

		// 用户标识
		// env.put(CMQC.USER_ID_PROPERTY, "test");

		// 设置目标队列管理器
		queueManagerName = "GWI.QM";
		// 设置目标队列
		queueName = "IN.BS369.LQ";

		// 建立队列管理器连接
		connectQM();
	}

	/**
	 * 程序结束时释放队列管理连接资源
	 * 
	 * @throws Exception
	 */
	public static void destroyEnvironment() throws Exception {
		disconnectQM();
	}

	/**
	 * 建立连接
	 * 
	 * @throws Exception
	 */
	private static void connectQM() throws Exception {
		queueManager = new MQQueueManager(queueManagerName, env);
	}

	/**
	 * 释放连接
	 * 
	 * @throws Exception
	 */
	private static void disconnectQM() throws Exception {
		if (queueManager != null) {
			queueManager.disconnect();
		}
	}

	private static Document getDocumentByString(String content) throws DocumentException {
		SAXReader reader = new SAXReader();
		InputStream is = new ByteArrayInputStream(content.getBytes());
		Document document = reader.read(is);
		return document;
	}

	private static Map<String, String> getMessageHeaderProperties(String request_data) throws DocumentException {
		Map<String, String> p = new HashMap<String, String>();

		Document document = getDocumentByString(request_data);
		Element root = document.getRootElement();
		Element placerGroup = root.element("controlActProcess").element("subject").element("placerGroup");

		Iterator<Element> domain_id = placerGroup.element("subject").element("patient").element("id")
				.elementIterator("item");
		domain_id.next();
		String hosNo = domain_id.next().attributeValue("extension");
		String visitNo = domain_id.next().attributeValue("extension");

		Iterator<Element> ls = placerGroup.element("componentOf1").element("encounter").element("id")
				.elementIterator("item");
		ls.next();
		String lsNo = ls.next().attributeValue("extension");

		// 检查申请时间
		String applytime = placerGroup.element("component2").element("observationRequest").element("effectiveTime")
				.element("any").attributeValue("value");

//		执行科室编码
		String zxksbm = placerGroup.element("component2").element("observationRequest").element("location")
				.element("serviceDeliveryLocation").element("serviceProviderOrganization").element("id").element("item")
				.attributeValue("extension");

//		执行科室名称
		String zxksmc = placerGroup.element("component2").element("observationRequest").element("location")
				.element("serviceDeliveryLocation").element("serviceProviderOrganization").element("name")
				.element("item").element("part").attributeValue("value");

//		医嘱组套编码
		String yztjbm = "5405201901070001";

//		医嘱组套名称
		String yztjmc = "动态心电图监测组套";

//		医生工号
		String kdysgh = placerGroup.element("author").element("assignedEntity").element("id").element("item")
				.attributeValue("extension");

//		医生姓名	
		String kdysxm = placerGroup.element("author").element("assignedEntity").element("assignedPerson")
				.element("name").element("item").element("part").attributeValue("value");

		// 就诊流水号

		p.put("hosNo", hosNo);
		p.put("visitNo", visitNo);
		p.put("lsNo", lsNo);

		p.put("applytime", applytime);
		p.put("zxksbm", zxksbm);
		p.put("zxksmc", zxksmc);
		p.put("yztjbm", yztjbm);
		p.put("yztjmc", yztjmc);

		p.put("kdysxm", kdysxm);

		p.put("kdysgh", kdysgh);

		System.out.println("===============================" + p);
		return p;
	}

	/**
	 * 发送原始的影像消息
	 * 
	 * @param sendQueueManager
	 * @param sendQueue
	 * @throws Exception
	 */
	public static void findAllReportsImgAndSendMessage() throws Exception {

		while (true) {
			List<BSImgBean> list = DbUtil.findAllReportImgToSent();

			if (list.size() > 0) {

				// 如果集合有值则开始发送消息
				System.out.format("%s: BSIMG list size: %s\r\n",
						new SimpleDateFormat("yyyyMMdd_HHmmss.SSS").format(Calendar.getInstance().getTime()),
						list.size());
				for (int i = 0; i < list.size(); i++) {
					if (i == 0) {
						// 第一次建立queueManager
						initEnvironment();
						// 队列打开参数
						int openOptions = MQConstants.MQOO_BIND_AS_Q_DEF | MQConstants.MQOO_OUTPUT;
						// 打开队列(同一线程内，同时只能打开该队列一次)
						queue = queueManager.accessQueue(queueName, openOptions);

					}

					// 设置发送消息参数为：具有同步性，及支持事务
					MQPutMessageOptions pmo = new MQPutMessageOptions();
					pmo.options = MQConstants.MQPMO_SYNCPOINT;
					try {

						MQMessage msg = null;
						// 设置消息格式为字符串类型
						msg = new MQMessage();
						msg.format = MQConstants.MQFMT_STRING;
						// 设置自定义消息头（厂商接入时根据自己的业务设定消息头）
						// 医疗机构代码
						msg.setStringProperty("hospital_id", "46600083-8");
						// 消息ID
						msg.setStringProperty("service_id", "BS369");
						// 就诊类别ID(01 门诊,2 急诊,0201 普通急诊,0202 急诊留观,03 住院,04 体检,0401 普通体检,0402 干保体检,05 转院)
						msg.setStringProperty("domain_id", "03");
						// 申请科室ID
						msg.setStringProperty("apply_unit_id", "010101010117");
						// 发送系统ID
						msg.setStringProperty("send_sys_id", "S119");
						// 执行科室ID
						msg.setStringProperty("exec_unit_id", "010101010117");
						// 医嘱执行分类编码
						msg.setStringProperty("order_exec_id", "0");
						// 扩展码（empi使用时放入域ID，其它系统标0）
						msg.setStringProperty("extend_sub_id", "0");

						// 消息内容编码(1208:utf-8)
						msg.characterSet = 1208;

						// 业务体 begin

						BSImgBean bSImg = list.get(i);

						String result = BzUtil.downloadFile(bSImg.getFilekey());
						// reqData check_interface 中的原始数据
						String reqData = bSImg.getRequestData();

						Map<String, String> m = getMessageHeaderProperties(reqData);

						// 住院号
						String hosNo = m.get("hosNo").toString();
						// 就诊号
						String visitNo = m.get("visitNo").toString();
						// 流水号
						String lsNo = m.get("lsNo").toString();
						// 检查申请时间
						String applytime = m.get("applytime").toString();

						// 执行科室编码
						String zxksbm = m.get("zxksbm").toString();

						// 执行科室名称
						String zxksmc = m.get("zxksmc").toString();

						// 医嘱组套编码
						String yztjbm = m.get("yztjbm").toString();

						// 医嘱组套名称
						String yztjmc = m.get("yztjmc").toString();

						// 医生姓名
						String kdysxm = m.get("kdysxm").toString();

						// 医生工号
						String kdysgh = m.get("kdysgh").toString();

						PhotoBean pm = new PhotoBean(DateTime.now().toString("yyyyMMddHHmm"), bSImg.getVisitNo(), hosNo,
								bSImg.getBedCode(), bSImg.getPatientName(), bSImg.getSex(), "", "", bSImg.getCcTime(),
								bSImg.getaDocName(), bSImg.getrTime(), bSImg.getrDocName(), bSImg.getDocAdviceId(),
								result, visitNo, lsNo, applytime, zxksbm, zxksmc, yztjbm, yztjmc, kdysxm, kdysgh);

						String message = FileUtil
								.replaceByXMLPhoto(FileUtils.readFileToString(new File("13815948.xml")), pm);
						// 业务体 end
						// 设置消息内容
						msg.writeString(message);
						// 消息放入隊列
						queue.put(msg, pmo);

						// 提交事务
						queueManager.commit();

						// 在项目路径msg中存放消息日志
						BzUtil.dumpMsg(message, "BSIMG",
								new SimpleDateFormat("yyyyMMdd_HHmmssSSS").format(Calendar.getInstance().getTime()));
						// 消息上传完后状态改为1
						WriteMysql.updateImgStatusByS3Key(bSImg.getcResultId(), 1);
						// 发送消息请求时间
						System.out.format("%s: Send BSIMG message seq %s begin!\r\n",
								new SimpleDateFormat("yyyyMMdd_HHmmss.SSS").format(Calendar.getInstance().getTime()),
								i);

						System.out.println("发送成功！");

						String str = SimpleStringUtil2.Bytes2HexString(msg.messageId).toLowerCase();
						// 返回的消息id
						System.out.println("MsgId:" + str.length() + "~~~~MsgId:" + str);

					} catch (MQException e) {
						// 事务回滚
						queueManager.backout();
						// e.printStackTrace();
						if (e.reasonCode == MQConstants.MQRC_CHANNEL_NOT_AVAILABLE
								|| e.reasonCode == MQConstants.MQRC_CONNECTION_BROKEN
								|| e.reasonCode == MQConstants.MQRC_CONNECTION_ERROR
								|| e.reasonCode == MQConstants.MQRC_CONNECTION_STOPPED
								|| e.reasonCode == MQConstants.MQRC_Q_MGR_QUIESCING) {
							// 设定重新连接（接入厂商考虑重新连接设定）
							connectQM();
							System.out.println("队列管理器连接不可用，需要重新创建队列管理器!");
						} else {
							e.printStackTrace();
							throw e;
						}
					} finally {

					}

					Thread.sleep(2000);

				}
			} else {
				System.out.println("findAllReportsImgAndSendMessage——list =0 ");
			}
		}

	}

	/**
	 * 发送已签名的影像消息 在consultation_result表里查询
	 * 
	 * @param sendQueueManager
	 * @param sendQueue
	 * @throws Exception
	 */
	public static void findAllReportsImgSignAndSendMessage() throws Exception {

		while (true) {
			List<BSImgBean> list = DbUtil.findAllReportImgSignToSent();

			if (list.size() > 0) {
				System.out.format("%s: findAllReportsImgSignAndSendMessage list size: %s\r\n",
						new SimpleDateFormat("yyyyMMdd_HHmmss.SSS").format(Calendar.getInstance().getTime()),
						list.size());

				for (int i = 0; i < list.size(); i++) {
					if (i == 0) {
						// 第一次建立queueManager
						initEnvironment();
						// 队列打开参数
						int openOptions = MQConstants.MQOO_BIND_AS_Q_DEF | MQConstants.MQOO_OUTPUT;
						// 打开队列(同一线程内，同时只能打开该队列一次)
						queue = queueManager.accessQueue(queueName, openOptions);

					}

					// 设置发送消息参数为：具有同步性，及支持事务
					MQPutMessageOptions pmo = new MQPutMessageOptions();
					pmo.options = MQConstants.MQPMO_SYNCPOINT;
					try {

						MQMessage msg = null;
						// 设置消息格式为字符串类型
						msg = new MQMessage();
						msg.format = MQConstants.MQFMT_STRING;
						// 设置自定义消息头（厂商接入时根据自己的业务设定消息头）
						// 医疗机构代码
						msg.setStringProperty("hospital_id", "46600083-8");
						// 消息ID
						msg.setStringProperty("service_id", "BS369");
						// 就诊类别ID(01 门诊,2 急诊,0201 普通急诊,0202 急诊留观,03 住院,04 体检,0401 普通体检,0402 干保体检,05 转院)
						msg.setStringProperty("domain_id", "03");
						// 申请科室ID
						msg.setStringProperty("apply_unit_id", "010101010117");
						// 发送系统ID
						msg.setStringProperty("send_sys_id", "S119");
						// 执行科室ID
						msg.setStringProperty("exec_unit_id", "010101010117");
						// 医嘱执行分类编码
						msg.setStringProperty("order_exec_id", "0");
						// 扩展码（empi使用时放入域ID，其它系统标0）
						msg.setStringProperty("extend_sub_id", "0");

						// 消息内容编码(1208:utf-8)
						msg.characterSet = 1208;

						// 业务体 begin

						BSImgBean bSImg = list.get(i);

						String result = BzUtil.downloadFile(bSImg.getFilekey());

						String reqData = bSImg.getRequestData();

						Map<String, String> m = getMessageHeaderProperties(reqData);

						// 住院号
						String hosNo = m.get("hosNo").toString();
						// 就诊号
						String visitNo = m.get("visitNo").toString();
						// 流水号
						String lsNo = m.get("lsNo").toString();

						// 检查申请时间
						String applytime = m.get("applytime").toString();

						// 执行科室编码
						String zxksbm = m.get("zxksbm").toString();

						// 执行科室名称
						String zxksmc = m.get("zxksmc").toString();

						// 医嘱组套编码
						String yztjbm = m.get("yztjbm").toString();

						// 医嘱组套名称
						String yztjmc = m.get("yztjmc").toString();

						// 医生姓名
						String kdysxm = m.get("kdysxm").toString();

						// 医生工号
						String kdysgh = m.get("kdysgh").toString();

						PhotoBean pm = new PhotoBean(DateTime.now().toString("yyyyMMddHHmm"), bSImg.getVisitNo(), hosNo,
								bSImg.getBedCode(), bSImg.getPatientName(), bSImg.getSex(), "", "", bSImg.getCcTime(),
								bSImg.getaDocName(), bSImg.getrTime(), bSImg.getrDocName(), bSImg.getDocAdviceId(),
								result, visitNo, lsNo, applytime, zxksbm, zxksmc, yztjbm, yztjmc, kdysxm, kdysgh);

						System.out.format("%s: Send findAllReportsImgSignAndSendMessage message seq %s begin!\r\n",
								new SimpleDateFormat("yyyyMMdd_HHmmss.SSS").format(Calendar.getInstance().getTime()),
								i);

						String message = FileUtil
								.replaceByXMLPhoto(FileUtils.readFileToString(new File("13815948_sign.xml")), pm);

						// 业务体 end
						// 设置消息内容
						msg.writeString(message);
						// 消息放入隊列
						queue.put(msg, pmo);

						// 提交事务
						queueManager.commit();

						// 在项目路径msg中存放消息日志
						BzUtil.dumpMsg(message, "BSIMGSING",
								new SimpleDateFormat("yyyyMMdd_HHmmssSSS").format(Calendar.getInstance().getTime()));
						// 消息上传完后状态改为2
						WriteMysql.updateImgStatusByS3Key(bSImg.getcResultId(), 2);
						// 发送消息请求时间
						System.out.format("%s: Send BSIMG message seq %s begin!\r\n",
								new SimpleDateFormat("yyyyMMdd_HHmmss.SSS").format(Calendar.getInstance().getTime()),
								i);

						System.out.println("发送成功！");

						String str = SimpleStringUtil2.Bytes2HexString(msg.messageId).toLowerCase();
						// 返回的消息id
						System.out.println("MsgId:" + str.length() + "~~~~MsgId:" + str);

					} catch (MQException e) {
						// 事务回滚
						queueManager.backout();
						// e.printStackTrace();
						if (e.reasonCode == MQConstants.MQRC_CHANNEL_NOT_AVAILABLE
								|| e.reasonCode == MQConstants.MQRC_CONNECTION_BROKEN
								|| e.reasonCode == MQConstants.MQRC_CONNECTION_ERROR
								|| e.reasonCode == MQConstants.MQRC_CONNECTION_STOPPED
								|| e.reasonCode == MQConstants.MQRC_Q_MGR_QUIESCING) {
							// 设定重新连接（接入厂商考虑重新连接设定）
							connectQM();
							System.out.println("队列管理器连接不可用，需要重新创建队列管理器!");
						} else {
							e.printStackTrace();
							throw e;
						}
					} finally {

					}

					Thread.sleep(2000);

				}
			}
		}

	}

	public static void main(String[] args) throws IOException, DocumentException {

		String content = FileUtils.readFileToString(new File("xml.txt"));
		Map<String, String> m = getMessageHeaderProperties(content);

		// 住院号
		String hosNo = m.get("hosNo").toString();
		// 就诊号
		String visitNo = m.get("visitNo").toString();
		// 流水号
		String lsNo = m.get("lsNo").toString();

		String date = "2018-11-21 14:27:24";
	}

}
